package com.songlanyun.modules.wechat.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.live.WxMaLiveResult;
import cn.binarywang.wx.miniapp.json.WxMaGsonBuilder;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.modules.wechat.config.WxMaConfiguration;
import com.songlanyun.modules.wechat.dao.WechatLiveDao;
import com.songlanyun.modules.wechat.dto.WxMaLiveInfo;
import com.songlanyun.modules.wechat.entity.WechatLive;
import com.songlanyun.modules.wechat.service.WechatLiveGoodsService;
import com.songlanyun.modules.wechat.service.WechatLiveService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.Broadcast.Room.*;

/**
 * 商家店铺中的商品分组
 */
@Service("wechatLiveService")
@Slf4j
public class WechatLiveServiceImpl extends ServiceImpl<WechatLiveDao, WechatLive> implements WechatLiveService {

    @Value("${wx.miniapp.configs[0].appid}")
    private String appid;

    @Value("${wx.miniapp.configs[0].upload}")
    private String uploadDirStr;

    @Autowired
    WechatLiveGoodsService wechatLiveGoodsService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WechatLive create(WechatLive entity) {
        try {
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            WxMaLiveInfo.RoomInfo roomInfo = new WxMaLiveInfo.RoomInfo();
            BeanUtils.copyProperties(entity, roomInfo);
            roomInfo.setFeedsImg(uploadPhotoToWx(wxMaService, entity.getFeedsImge()));
            roomInfo.setAnchorImg(uploadPhotoToWx(wxMaService, entity.getAnchorImge()));
            roomInfo.setCoverImg(uploadPhotoToWx(wxMaService, entity.getCoverImge()));
            roomInfo.setShareImg(uploadPhotoToWx(wxMaService, entity.getShareImge()));
            roomInfo.setStartTime(Long.valueOf(dateToTimestamp(entity.getStartTime())));
            roomInfo.setEndTime(Long.valueOf(dateToTimestamp(entity.getEndTime())));
            Integer roomId = this.createRoom(roomInfo);
            entity.setRoomId(Long.valueOf(roomId));
            this.baseMapper.insert(entity);
        } catch (WxErrorException e) {
            e.printStackTrace();
            String error = e.toString();
            if (error.indexOf("anchorWechat has no realName") != -1) {
                throw new RuntimeException("微信调用失败！主播微信号未实名");
            } else if (error.indexOf("parameter startTime or endTime is invalid") != -1) {
                throw new RuntimeException("微信调用失败！直播时间错误");
            } else if (error.indexOf("parameter anchorname length is invalid") != -1) {
                throw new RuntimeException("微信调用失败！主播昵称最短2个汉字");
            } else if (error.indexOf("parameter name length is invalid") != -1) {
                throw new RuntimeException("微信调用失败！直播间名字，最短3个汉字，最长17个汉字");
            } else {
                throw new RuntimeException("微信调用失败！" + e.toString());
            }
        }
        return entity;
    }


    @Override
    public WechatLive modify(WechatLive entity) {
        try {
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            WxMaLiveInfo.RoomInfo roomInfo = new WxMaLiveInfo.RoomInfo();
            BeanUtils.copyProperties(entity, roomInfo);
            roomInfo.setId(entity.getRoomId().intValue());
            roomInfo.setFeedsImg(uploadPhotoToWx(wxMaService, entity.getFeedsImge()));
            roomInfo.setAnchorImg(uploadPhotoToWx(wxMaService, entity.getAnchorImge()));
            roomInfo.setCoverImg(uploadPhotoToWx(wxMaService, entity.getCoverImge()));
            roomInfo.setShareImg(uploadPhotoToWx(wxMaService, entity.getShareImge()));
            roomInfo.setStartTime(Long.valueOf(dateToTimestamp(entity.getStartTime())));
            roomInfo.setEndTime(Long.valueOf(dateToTimestamp(entity.getEndTime())));
            this.updateRoom(roomInfo);
            this.baseMapper.updateById(entity);
        } catch (WxErrorException e) {
            e.printStackTrace();
            String error = e.toString();
            if (error.indexOf("parameter startTime or endTime is invalid") != -1) {
                throw new RuntimeException("直播间时间错误");
            } else if (error.indexOf("200002") != -1) {
                throw new RuntimeException("参数错误");
            } else if (error.indexOf("300002") != -1) {
                throw new RuntimeException("名称长度不符合规则");
            } else if (error.indexOf("300022") != -1) {
                throw new RuntimeException("此房间号不存在");
            } else if (error.indexOf("300023") != -1) {
                throw new RuntimeException("房间状态 拦截（当前房间状态不允许此操作）");
            } else if (error.indexOf("300030") != -1) {
                throw new RuntimeException("主播微信号不合法");
            } else if (error.indexOf("300037") != -1) {
                throw new RuntimeException("购物直播频道封面图不合规");
            } else if (error.indexOf("300031") != -1) {
                throw new RuntimeException("直播间封面图不合规");
            } else if (error.indexOf("300032") != -1) {
                throw new RuntimeException("直播间分享图违规");
            } else {
                throw new RuntimeException("微信调用失败！" + e.toString());
            }
        }
        return this.getById(entity.getRoomId());
    }

    @Override
    public void remove(Long id) {
        try {
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            JSONObject reqBody = new JSONObject();
            reqBody.put("id", id);
            String responseContent = wxMaService.post(DELETE_ROOM, WxMaGsonBuilder.create().toJson(reqBody));
            this.removeById(id);
        } catch (WxErrorException e) {
            e.printStackTrace();
            String error = e.toString();
            if (error.indexOf("200002") != -1) {
                throw new RuntimeException("参数错误");
            } else if (error.indexOf("300022") != -1) {
                throw new RuntimeException("此房间号不存在");
            } else if (error.indexOf("300023") != -1) {
                throw new RuntimeException("房间状态 拦截（当前房间状态不允许此操作）");
            } else {
                throw new RuntimeException("微信调用失败！" + e.toString());
            }
        }
    }


    @Override
    public boolean addProduct(WechatLive entity) {
        try {
            WechatLive wechatLiveDB = this.baseMapper.selectById(entity.getRoomId());
            //新增
            String[] goodsIdArray = entity.getWxGoodsIds().split(",");
            String wxGoodsIds = "";
            if (StringUtils.isNotBlank(wechatLiveDB.getWxGoodsIds())) {
                wxGoodsIds = wechatLiveDB.getWxGoodsIds();
            }
            String[] dbGoodsIdArray = wxGoodsIds.split(",");
            //比对出新增的ID
            List<String> difference = Arrays.asList(goodsIdArray).stream().filter(element -> !Arrays.asList(dbGoodsIdArray).contains(element)).collect(Collectors.toList());
            List<Integer> integerList = difference.stream().map(Integer::parseInt).collect(Collectors.toList());
            // 输出转换后的整数列表
            System.out.println("差集为：" + difference);
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            Boolean mark = wxMaService.getLiveService().addGoodsToRoom(entity.getRoomId().intValue(), integerList);
            if (!mark) {
                throw new RuntimeException("添加到直播间商品失败");
            }
            this.baseMapper.updateById(entity);
        } catch (Exception e) {
            String error = e.toString();
            if (error.indexOf("200002") != -1) {
                throw new RuntimeException("入参错误");
            } else if (error.indexOf("300022") != -1) {
                throw new RuntimeException("此房间号不存在");
            } else if (error.indexOf("300023") != -1) {
                throw new RuntimeException("房间状态 拦截（当前房间状态不允许此操作)");
            } else if (error.indexOf("300024") != -1) {
                throw new RuntimeException("商品不存在");
            } else if (error.indexOf("300025") != -1) {
                throw new RuntimeException("商品审核未通过");
            } else if (error.indexOf("300027") != -1) {
                throw new RuntimeException("商品添加成功，审核失败");
            } else if (error.indexOf("300033") != -1) {
                throw new RuntimeException("商品图片尺寸过大");
            } else if (error.indexOf("300010") != -1) {
                throw new RuntimeException("商品审核中不允许修改");
            } else {
                throw new RuntimeException("微信调用失败！" + e.toString());
            }
        }
        return true;
    }

    @Override
    public boolean removeProduct(WechatLive entity) {
        try {
            WechatLive wechatLiveDB = this.baseMapper.selectById(entity.getRoomId());
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            if (StringUtils.isNotBlank(entity.getWxGoodsIds())) {
                //上下架 【0：下架，1：上架】
                Boolean mark = wxMaService.getLiveService().onsale(entity.getRoomId().intValue(), Integer.parseInt(entity.getWxGoodsIds()), 0);
                if (!mark) {
                    throw new RuntimeException("下架商品失败");
                }
                String[] pids = wechatLiveDB.getWxGoodsIds().split(",");
                String[] result = Arrays.stream(pids).distinct().toArray(String[]::new);
                String updateGoodsIds = "";
                for (int i = 0; i < result.length; i++) {
                    if (!entity.getWxGoodsIds().equals(result[i])) {
                        updateGoodsIds = updateGoodsIds + "," + result[i];
                    }
                }
                if (updateGoodsIds.indexOf(",") == 0) {
                    updateGoodsIds = updateGoodsIds.substring(1);
                }
                entity.setWxGoodsIds(updateGoodsIds);
                this.baseMapper.updateById(entity);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
        return true;
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String name = MapUtil.getStr(params, "name");
        Integer liveStatus = MapUtil.getInt(params, "liveStatus");
        IPage<WechatLive> page = this.page(
                new Query<WechatLive>().getPage(params),
                new LambdaQueryWrapper<WechatLive>()
                        .like(StringUtils.isNotBlank(name), WechatLive::getName, name)
                        .eq(liveStatus != null, WechatLive::getLiveStatus, liveStatus)
        );
        return new PageUtils(page);
    }


    @Override
    public List<WechatLive> queryAll() {
        LambdaQueryWrapper<WechatLive> wechatLiveLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wechatLiveLambdaQueryWrapper.lt(WechatLive::getLiveStatus, 104);
        return this.baseMapper.selectList(wechatLiveLambdaQueryWrapper);
    }


    @Override
    public PageUtils queryPage4API(Map<String, Object> params) {
        Integer liveStatus = MapUtil.getInt(params, "liveStatus");
        IPage<WechatLive> page = this.page(
                new Query<WechatLive>().getPage(params),
                new LambdaQueryWrapper<WechatLive>()
                        .lt(liveStatus == null, WechatLive::getLiveStatus, 104)
                        .eq(liveStatus != null, WechatLive::getLiveStatus, liveStatus)
        );
        return new PageUtils(page);
    }

    /**
     * 同步直播间
     *
     * @return
     */
    @Override
    public boolean synchroWxOlLive() {
        try {
            WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
            List<WxMaLiveResult.RoomInfo> liveInfos = wxMaService.getLiveService().getLiveInfos();
            if (liveInfos != null && liveInfos.size() > 0) {
                WechatLive wechatLive;
                for (WxMaLiveResult.RoomInfo roomInfo : liveInfos) {
                    wechatLive = this.baseMapper.selectById(roomInfo.getRoomId());
                    if (wechatLive == null) {
                        continue;
                    }
                    wechatLive.setLiveStatus(roomInfo.getLiveStatus());
                    this.baseMapper.updateById(wechatLive);
                }
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return true;
    }


    private Integer createRoom(WxMaLiveInfo.RoomInfo roomInfo) throws WxErrorException {
        WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
        String responseContent = wxMaService.post(CREATE_ROOM, WxMaGsonBuilder.create().toJson(roomInfo));
        JSONObject jsonObject = JSONObject.parseObject(responseContent);
        if (jsonObject.getInteger("errcode") != 0) {
            throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
        }
        return jsonObject.getInteger("roomId");
    }

    private Integer updateRoom(WxMaLiveInfo.RoomInfo roomInfo) throws WxErrorException {
        WxMaService wxMaService = WxMaConfiguration.getMaService(appid);
        String responseContent = wxMaService.post(EDIT_ROOM, WxMaGsonBuilder.create().toJson(roomInfo));
        JSONObject jsonObject = JSONObject.parseObject(responseContent);
        if (jsonObject.getInteger("errcode") != 0) {
            throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp));
        }
        return jsonObject.getInteger("roomId");
    }

    /**
     * 上传临时素材
     *
     * @param wxMaService WxMaService
     * @param picPath     图片路径
     * @return WxMpMaterialUploadResult
     * @throws WxErrorException
     */
    private String uploadPhotoToWx(WxMaService wxMaService, String picPath) throws WxErrorException {
        if (StringUtils.isNotBlank(picPath)) {
            String filename = (int) System.currentTimeMillis() + ".png";
            String downloadPath = uploadDirStr + filename;
            long size = HttpUtil.downloadFile(picPath, cn.hutool.core.io.FileUtil.file(downloadPath));
            picPath = downloadPath;
            File picFile = new File(picPath);
            log.info("picFile name : {}", picFile.getName());
            WxMediaUploadResult wxMediaUploadResult = wxMaService.getMediaService().uploadMedia(WxConsts.MediaFileType.IMAGE, picFile);
            log.info("wxMpMaterialUploadResult : {}", JSONUtil.toJsonStr(wxMediaUploadResult));
            if (wxMediaUploadResult != null) {
                return wxMediaUploadResult.getMediaId();
            }
        }
        return "";
    }

    /**
     * 获取精确到秒的时间戳
     *
     * @return
     **/
    protected int dateToTimestamp(Date date) {
        String timestamp = String.valueOf(date.getTime() / 1000);
        return Integer.valueOf(timestamp);
    }


}
